/*
 * Copyright (C) 2024 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the 'License');
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an 'AS IS' BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "transformation/gputransform/imageknife_egl.h"
#include "imageknife_dispatcher.h"
#include "downsampling/down_sampler.h"
#include "file_cache.h"
#include "task_worker.h"
#include "memory_cache.h"
#include "imageknife_loader.h"
#include "task_worker.h"
#include "imageknife_internal.h"
#include "imageknife_task_internal.h"
#include "loader/imageknife_loader_internal.h"
#include "imageknife_data_napi.h"
#include "image_data_cache_internal.h"
#include "libbase64.h"
#include "securec.h"

namespace ImageKnifePro {

ImageKnifeDispatcher::ImageKnifeDispatcher()
{
}

ImageKnifeDispatcher::~ImageKnifeDispatcher()
{
    if (jobQueuePtr_ != nullptr) {
        delete jobQueuePtr_;
    }
}

std::string GetTransformInfo(std::shared_ptr<ImageKnifeOption> option, ImageRequestType type)
{
    if (option == nullptr || type != ImageRequestType::MAIN_SRC) {
        return std::string();
    }

    if (option->multiTransformation != nullptr) {
        return option->multiTransformation->GetTransformInfo();
    } else if (option->transformation != nullptr) {
        return option->transformation->GetTransformInfo();
    }

    return std::string();
}

std::string GetDownSampleInfo(std::shared_ptr<ImageKnifeNodeInternal> node, DownSamplingStrategy strategy)
{
    if (node != nullptr) {
        return DownSampler::GetDownSamplingInfo(node->GetComponentSize(), strategy);
    }

    return DownSampler::GetDownSamplingInfo({0, 0}, strategy);
}

bool GetAnimatorInfo(std::shared_ptr<ImageKnifeNodeInternal> node, std::shared_ptr<ImageKnifeRequestInternal> request)
{
    if (node != nullptr) {
        return node->IsAnimator();
    } else {
        return request->IsPreloadAnimator();
    }
}

IJobQueue::Job ImageKnifeDispatcher::GenerateJob(std::shared_ptr<ImageKnifeRequestInternal> request,
                                                 ImageRequestType type)
{
    IMAGE_KNIFE_CHECK_RETURN(request == nullptr, IJobQueue::Job());
    auto option = request->GetImageKnifeOption();
    IMAGE_KNIFE_CHECK_RETURN(option == nullptr, IJobQueue::Job());

    auto generator = ImageKnifeInternal::GetInstance().GetCacheKeyGenerator();
    IMAGE_KNIFE_CHECK_RETURN(generator == nullptr, IJobQueue::Job());

    IJobQueue::Job job = {.request = request, .imageSrc = GetImageSrc(option, type), .type = type};
    if (job.imageSrc == nullptr) {
        return job;
    }

    std::shared_ptr<ImageKnifeNodeInternal> node = nullptr;
    if (!request->IsPreload()) {
        node = ImageKnifeInternal::GetInstance().GetImageNode(request->GetNodeId());
    }

    if (node != nullptr && type == ImageRequestType::MAIN_SRC) {
        // 已生成的主图key不必重复生成
        job.memoryKey = node->GetMainSrcKey();
    }

    if (job.memoryKey.empty()) {
        CacheKeyGenerator::MemoryKeyParams params = {.imageSource = job.imageSrc, .type = type,
                                                     .signature = option->signature,
                                                     .transformationInfo = GetTransformInfo(option, type),
                                                     .downSamplingInfo = GetDownSampleInfo(node, option->downSampling),
                                                     .isAnimator = GetAnimatorInfo(node, request)};

        if (option->context.config != nullptr) {
            params.colorMode = option->context.config->colorMode;
        }
        job.memoryKey = generator->GenerateMemoryKey(params);
        // 组件记录主图memoryKey
        if (type == ImageRequestType::MAIN_SRC && node != nullptr) {
            node->SetMainSrcKey(job.memoryKey);
        }
    }

    job.fileKey = generator->GenerateFileKey(job.imageSrc, type == ImageRequestType::MAIN_SRC ? option->signature : "");
    return job;
}

void ImageKnifeDispatcher::Enqueue(std::shared_ptr<ImageKnifeRequestInternal> request)
{
    IMAGE_KNIFE_CHECK(request == nullptr);
    request->GetImageInfo().timeInfo.executeTime = ImageKnifeDataNapi::GetTimestamp();
    request->GetImageInfo().requestId = request->GetRequestId();

    auto option = request->GetImageKnifeOption();
    IMAGE_KNIFE_CHECK(option == nullptr);

    if (option->imageLoader == nullptr) {
        // 设置使用默认的loader
        option->imageLoader = ImageKnifeInternal::GetInstance().GetDefaultImageKnifeLoader();
        if (option->imageLoader == nullptr) {
            IMAGE_KNIFE_LOG(LOG_ERROR, "Can't find ImageKnifeLoader");
            if (option->onLoadListener != nullptr && option->onLoadListener->onLoadFailed != nullptr) {
                option->onLoadListener->onLoadFailed("Can't find ImageKnifeLoader", request->GetImageInfo());
            }
            return;
        }
    }

    request->GetImageInfo().errorInfo.phase = ImageKnifeDataNapi::phaseToStringMap[LoadPhase::MEMORY_CACHE];
    request->GetImageInfo().timeInfo.memoryCheckStartTime = ImageKnifeDataNapi::GetTimestamp();
    auto mainJob = GenerateJob(request, ImageRequestType::MAIN_SRC);
    if (mainJob.imageSrc == nullptr) {
        ProcessFailedRequest(request, ImageRequestType::MAIN_SRC, "Empty MainSrc (GetImageSrc)");
        return;
    }

    // 有内存的情况直接显示
    if (LoadSrcFromMemory(mainJob)) {
        return;
    }

    auto placeJob = GenerateJob(request, ImageRequestType::PLACE_SRC);
    bool foundPlaceHolder = LoadSrcFromMemory(placeJob);

    // 判断是否排队
    if (executingJobMap_.size() >= maxRequests) {
        IMAGE_KNIFE_LOG(LOG_DEBUG, "%{public}s Request Enqueue",
                        ImageKnifeTaskInternal::GetTaskInfo(ImageRequestType::MAIN_SRC, request).c_str());
        jobQueuePtr_->Add(mainJob);

        if (placeJob.imageSrc != nullptr && !foundPlaceHolder && !request->IsSyncLoad()) {
            IMAGE_KNIFE_LOG(LOG_DEBUG, "%{public}s Request Enqueue",
                            ImageKnifeTaskInternal::GetTaskInfo(ImageRequestType::PLACE_SRC, request).c_str());
            jobQueuePtr_->Add(placeJob);
        }
        return;
    }

    // 启动加载主图
    ExecuteJob(mainJob);

    // 启动加载占位图
    if (placeJob.imageSrc != nullptr && !foundPlaceHolder && !request->IsSyncLoad()) {
        ExecuteJob(placeJob);
    }
}

bool ImageKnifeDispatcher::EncodeSourceBase64(std::shared_ptr<ImageKnifeTaskInternal> task)
{
    IMAGE_KNIFE_CHECK_RETURN(task == nullptr, false);
    std::string info = task->GetTaskInfo(task->GetImageRequestType(), task->GetImageKnifeRequestInternal());
    IMAGE_KNIFE_LOG(LOG_DEBUG, "%{public}s Encode Base64", info.c_str());
    std::string prefix = "data:image/";
    if (task->GetImageBufferFormat() == ImageFormat::GIF) {
        prefix += "gif;base64,";
    } else if (task->GetImageBufferFormat() == ImageFormat::WEBP) {
        prefix += "webp;base64,";
    } else {
        task->EchoError("Not An Animation Source (Encode Base64)");
        return false;
    }

    const char *source = nullptr;
    size_t length = 0;
    if (task->product.imageBuffer != nullptr) {
        source = reinterpret_cast<char *>(task->product.imageBuffer.get());
        length = task->product.imageLength;
    } else {
        return false;
    }

    // 编码后size增加至原本的4/3,再加上前缀和尾0
    const size_t incrementalSize = length * 4 / 3 + prefix.size() + 1;

    char *out = new char[incrementalSize];
    out[incrementalSize - 1] = 0; // 设置字符串尾0
    if (strcpy_s(out, incrementalSize, prefix.c_str()) != 0) {
        delete[] out;
        return false;
    }
    size_t outLength = 0;

    const int plainCodec = 1 << 3;
    base64_encode(source, length, out + prefix.size(), &outLength, plainCodec);
    task->product.imageDataCache = std::make_shared<ImageDataCacheInternal>(out);
    return true;
}

bool ImageKnifeDispatcher::ProduceImageCache(std::shared_ptr<ImageKnifeTaskInternal> task)
{
    IMAGE_KNIFE_CHECK_RETURN(task == nullptr, false);
    std::shared_ptr<ImageDataCacheInternal> imageDataCache;
    if (task->product.imageDataCache != nullptr) {
        // 已经构造了base64类型的缓存对象
        imageDataCache = std::static_pointer_cast<ImageDataCacheInternal>(task->product.imageDataCache);
    } else if (task->product.imageData->GetPixelmapList() != nullptr) {
        imageDataCache = std::make_shared<ImageDataCacheInternal>(task->product.imageData, task->IsAnimator());
    } else {
        task->EchoError("ImageData Unavailable (Produce ImageCache)");
        return false;
    }

    auto request = task->GetImageKnifeRequestInternal();
    IMAGE_KNIFE_CHECK_RETURN(request == nullptr, false);

    imageDataCache->type = task->GetImageBufferFormat();
    imageDataCache->imageWidth = request->GetImageInfo().imageWidth;
    imageDataCache->imageHeight = request->GetImageInfo().imageHeight;
    if (task->GetImageRequestType() == ImageRequestType::MAIN_SRC) {
        request->GetImageInfo().httpCode = task->httpCode;
    }
    task->product.imageDataCache = imageDataCache;
    return true;
}

bool ImageKnifeDispatcher::ProcessImageDecodeTransform(std::shared_ptr<ImageKnifeTaskInternal> task)
{
    IMAGE_KNIFE_CHECK_RETURN(task == nullptr, false);

    auto request = task->GetImageKnifeRequestInternal();
    IMAGE_KNIFE_CHECK_RETURN(request == nullptr, false);

    auto option = request->GetImageKnifeOption();
    IMAGE_KNIFE_CHECK_RETURN(option == nullptr, false);

    auto imageLoader = std::dynamic_pointer_cast<ImageKnifeLoaderInternal>(option->imageLoader);
    IMAGE_KNIFE_CHECK_RETURN(imageLoader == nullptr, false);

    // 判断图片类型,如果是普通Image组件,且图片为动图,则转换为Base64, 跳过解码与图形变换
    task->QueryImageBufferFormat();
    if (!task->IsAnimator() && task->IsAnimationImage()) {
        return EncodeSourceBase64(task);
    } else {
        // 图片解码
        bool decodeResult = imageLoader->DecodeImage(task);
        if (!decodeResult || task->IsFatalErrorHappened()) {
            if (task->GetLastError().empty()) {
                task->EchoError("Image Decode Error! (Loading), ImageFormat:" +
                                std::to_string(static_cast<int>(task->GetImageBufferFormat())));
            }
            return false;
        }

        if (task->product.imageData == nullptr) {
            task->EchoError("Empty ImageData After Decode (Loading)");
            return false;
        }

        if (task->GetImageRequestType() == ImageRequestType::MAIN_SRC) {
            request->GetImageInfo().frameCount = task->product.imageData->GetFrameCount();
            request->GetPixelMapInfo(task->product.imageData);
        }

        if (request->IsDestroy() || task->IsFatalErrorHappened()) {
            return false;
        }

        // 图片形变, 默认没有图片形变
        if (task->GetImageRequestType() == ImageRequestType::MAIN_SRC) {
            TransformImage(task);
            // 中止发生在图形变换阶段, pixelmap不符合内存缓存预期
            if (request->IsDestroy() || task->IsFatalErrorHappened()) {
                return false;
            }
        }
    }
    return true;
}

std::shared_ptr<ImageData> ImageKnifeDispatcher::LoadFromImageSourceSync(ImageSource *imageSource, Context context,
                                                                         std::string memoryKey, std::string fileKey)
{
    auto option = std::make_shared<ImageKnifeOption>();
    // 使用默认的loader
    option->imageLoader = ImageKnifeInternal::GetInstance().GetDefaultImageKnifeLoader();
    option->context = context;
    auto request = std::make_shared<ImageKnifeRequestInternal>(option);
    request->SetComponentId(request->GetNodeId() + "_ImageSrcSync");
    request->SyncLoad(true);

    // 生成task 以及key
    auto task = std::make_shared<ImageKnifeTaskInternal>(ImageRequestType::MAIN_SRC, request, imageSource);
    task->memoryKey = memoryKey;
    task->fileKey = fileKey;

    // 进行同步加载
    auto imageLoader = std::static_pointer_cast<ImageKnifeLoaderInternal>(option->imageLoader);
    if (!imageLoader->LoadFromMemory(task)) {
        LoadImageSource(task);
    }

    // 复用的resourceManager至空，避免重复析构
    option->context.resourceManager = nullptr;
    auto dataCache = std::dynamic_pointer_cast<ImageDataCacheInternal>(task->product.imageDataCache);
    if (dataCache == nullptr) {
        task->EchoError("empty imageData cache");
        return nullptr;
    }
    return dataCache->GetImageData();
}

void ImageKnifeDispatcher::LoadImageSource(std::shared_ptr<ImageKnifeTaskInternal> task)
{
    IMAGE_KNIFE_CHECK(task == nullptr);

    auto request = task->GetImageKnifeRequestInternal();
    IMAGE_KNIFE_CHECK(request == nullptr);

    auto option = request->GetImageKnifeOption();
    IMAGE_KNIFE_CHECK(option == nullptr);

    auto imageLoader = std::dynamic_pointer_cast<ImageKnifeLoaderInternal>(option->imageLoader);
    IMAGE_KNIFE_CHECK(imageLoader == nullptr);

    // 检查文件缓存: 只有主图并且设置了跳过文件缓存，才可以不执行
    if (!(request->IsFileCacheSkiped() && task->GetImageRequestType() == ImageRequestType::MAIN_SRC)) {
        task->foundFileCache = imageLoader->LoadFromFile(task);
    }

    if (request->IsDestroy() || task->IsFatalErrorHappened()) {
        return;
    }

    if (!task->foundFileCache && !ProcessImageLoading(task)) {
        return;
    }

    if (request->IsDestroy() || task->IsFatalErrorHappened()) {
        return;
    }

    if (!ProcessImageDecodeTransform(task)) {
        return;
    }

    if (!ProduceImageCache(task)) {
        return;
    }

    // 写内存缓存
    if (option->writeCacheStrategy == CacheStrategy::DEFAULT || option->writeCacheStrategy == CacheStrategy::MEMORY) {
        imageLoader->WriteCacheToMemory(task);
    }

    // 异步写文件缓存必须在内存缓存之后，否则task->cacheTask会有冲突
    ProcessFileCache(task);
    task->MarkSuccess();
}

bool ImageKnifeDispatcher::ProcessImageLoading(std::shared_ptr<ImageKnifeTaskInternal> task)
{
    IMAGE_KNIFE_CHECK_RETURN(task == nullptr, false);
    auto request = task->GetImageKnifeRequestInternal();
    IMAGE_KNIFE_CHECK_RETURN(request == nullptr, false);
    auto option = request->GetImageKnifeOption();
    IMAGE_KNIFE_CHECK_RETURN(option == nullptr, false);
    auto imageLoader = std::dynamic_pointer_cast<ImageKnifeLoaderInternal>(option->imageLoader);
    IMAGE_KNIFE_CHECK_RETURN(imageLoader == nullptr, false);
    
    // 仅使用缓存加载的情况下，没有对应缓存时结束加载
    if (task->GetImageRequestType() == ImageRequestType::MAIN_SRC && option->onlyRetrieveFromCache) {
        task->EchoError("No Cache Found When Using onlyRetrieveFromCache");
        return false;
    }
    // 加载责任链，网络下载等阶段
    if (!imageLoader->DownloadImage(task)) {
        if (task->GetLastError().empty()) {
            task->EchoError("load Image Failed! No useful error message (Loading)");
        }
        return false;
    }
    return true;
}

void ImageKnifeDispatcher::ProcessFileCache(std::shared_ptr<ImageKnifeTaskInternal> task)
{
    IMAGE_KNIFE_CHECK(task == nullptr);
    auto request = task->GetImageKnifeRequestInternal();
    IMAGE_KNIFE_CHECK(request == nullptr);
    auto option = request->GetImageKnifeOption();
    IMAGE_KNIFE_CHECK(option == nullptr);
    ImageSource *imageSrc = task->GetImageSource();
    IMAGE_KNIFE_CHECK(imageSrc == nullptr);

    if (task->foundFileCache || imageSrc->GetType() != DataType::STRING ||
        (option->writeCacheStrategy != CacheStrategy::DEFAULT && option->writeCacheStrategy != CacheStrategy::FILE)) {
        // 已找到文件缓存 或 图片类型是本地图片 或 缓存策略设置了不写文件缓存 的情况不写缓存
        return;
    }

    std::string loadSrc;
    imageSrc->GetString(loadSrc);
    if (loadSrc.empty() || loadSrc.find("/data/storage") == 0 || loadSrc.find("file:") == 0) {
        // 本地图库图片，沙箱路径图片不写文件缓存
        return;
    }

    auto imageLoader = std::dynamic_pointer_cast<ImageKnifeLoaderInternal>(option->imageLoader);
    IMAGE_KNIFE_CHECK(imageLoader == nullptr);

    auto func = [imageLoader](std::shared_ptr<ImageKnifeTaskInternal> task) {
        bool res = imageLoader->WriteCacheToFile(task);
        // 等待主线程根据请求合并的情况，返回preloadCache处理函数
        auto func = task->promisePreloadCache.get_future().get();
        if (func != nullptr) {
            func(res);
        }
        IMAGE_KNIFE_LOG(LOG_DEBUG, "%{public}s File Cache Thread End", task->GetTaskInfo().c_str());
    };

    TaskWorker::GetInstance()->PushTask(func, nullptr, task);
}

void ImageKnifeDispatcher::ProcessCanceledRequest(std::shared_ptr<ImageKnifeRequestInternal> request,
                                                  ImageRequestType type, std::string info, bool fromQueue)
{
    IMAGE_KNIFE_CHECK(request == nullptr);
    if (type == ImageRequestType::MAIN_SRC) {
        if (fromQueue) {
            request->GetImageInfo().errorInfo.code = LoadFailedCode::QUEUE_CANCEL;
        } else {
            request->GetImageInfo().errorInfo.code = LoadFailedCode::LOADING_CANCEL;
        }
        // 获取请求取消时间戳
        request->GetImageInfo().timeInfo.requestCancelTime = ImageKnifeDataNapi::GetTimestamp();
    }

    // 任务在执行中被取消
    std::string cancelInfo = ImageKnifeTaskInternal::GetTaskInfo(type, request) + info;
    IMAGE_KNIFE_LOG(LOG_DEBUG, "%{public}s", cancelInfo.c_str());
    auto option = request->GetImageKnifeOption();
    IMAGE_KNIFE_CHECK(option == nullptr);
    if (option->onLoadListener != nullptr && type == ImageRequestType::MAIN_SRC &&
        option->onLoadListener->onLoadCancel != nullptr) {
        option->onLoadListener->onLoadCancel(cancelInfo, request->GetImageInfo());
    }
}

void ImageKnifeDispatcher::ProcessSucceedRequest(std::shared_ptr<ImageKnifeRequestInternal> request,
                                                 ImageRequestType type,
                                                 std::shared_ptr<ImageKnifeTaskInternal> task)
{
    IMAGE_KNIFE_CHECK(request == nullptr);
    IMAGE_KNIFE_CHECK(task == nullptr);
    if (type != ImageRequestType::PLACE_SRC) {
        request->MarkStatusComplete();
    }

    if (type == ImageRequestType::MAIN_SRC) {
        request->GetImageInfo().timeInfo.requestEndTime = ImageKnifeDataNapi::GetTimestamp();
    }

    // 显示前打印图片信息info日志
    std::string info = ImageKnifeTaskInternal::GetTaskInfo(type, request);
    info += task->GetDisplayPixelmapInfo();
    IMAGE_KNIFE_LOG(LOG_INFO, "%{public}s", info.c_str());
    bool triggerCallback = true;
    // preload只加载不显示
    if (!request->IsPreload()) {
        request->MarkDisplayStartTime(type, false);
        triggerCallback = DisplayImage(request, type, task->product.imageDataCache);
    }

    auto option = request->GetImageKnifeOption();
    if (option->onLoadListener != nullptr && type == ImageRequestType::MAIN_SRC &&
        option->onLoadListener->onLoadSuccess != nullptr && triggerCallback) {
        // 触发onLoadSuccess回调
        option->onLoadListener->onLoadSuccess(request->GetImageInfo());
    }
}

void ImageKnifeDispatcher::ProcessFailedRequest(std::shared_ptr<ImageKnifeRequestInternal> request,
                                                ImageRequestType type, std::string errorInfo)
{
    IMAGE_KNIFE_CHECK(request == nullptr);
    auto option = request->GetImageKnifeOption();
    IMAGE_KNIFE_CHECK(option == nullptr);

    if (type == ImageRequestType::MAIN_SRC) {
        request->GetImageInfo().timeInfo.requestEndTime = ImageKnifeDataNapi::GetTimestamp();
    }

    std::string info = ImageKnifeTaskInternal::GetTaskInfo(type, request) + errorInfo;
    IMAGE_KNIFE_LOG(LOG_ERROR, "%{public}s", info.c_str());
    if (option->onLoadListener != nullptr && type == ImageRequestType::MAIN_SRC &&
        option->onLoadListener->onLoadFailed != nullptr) {
        option->onLoadListener->onLoadFailed(info, request->GetImageInfo());
    }
}

void ImageKnifeDispatcher::ProcessMainSrcFailedRequest(std::shared_ptr<ImageKnifeRequestInternal> request,
                                                       std::shared_ptr<ImageKnifeTaskInternal> task)
{
    IMAGE_KNIFE_CHECK(request == nullptr);
    // 失败时获取请求结束时间戳
    request->GetImageInfo().timeInfo.requestEndTime = ImageKnifeDataNapi::GetTimestamp();
    // 任务执行失败
    auto option = request->GetImageKnifeOption();
    IMAGE_KNIFE_CHECK(option == nullptr);
    if (option->onLoadListener != nullptr && option->onLoadListener->onLoadFailed != nullptr) {
        option->onLoadListener->onLoadFailed(task->GetLastError(), request->GetImageInfo());
    }

    if (request->IsDestroy()) {
        return;
    }
    // 主图失败启动错误占位图
    request->MarkStatusError();
    auto errorJob = GenerateJob(request, ImageRequestType::ERROR_SRC);
    if (errorJob.imageSrc != nullptr && !LoadSrcFromMemory(errorJob)) {
        // 如果被合并的请求的错误图不是同一张，则实际的请求数大于设置的最大并发数
        ExecuteJob(errorJob);
    }
}

bool ImageKnifeDispatcher::IsRequestOverdue(std::shared_ptr<ImageKnifeRequestInternal> request)
{
    IMAGE_KNIFE_CHECK_RETURN(request == nullptr, false);
    if (request->IsPreload()) {
        return false;
    }

    auto imageNode = ImageKnifeInternal::GetInstance().GetImageNode(request->GetNodeId());
    if (imageNode == nullptr || imageNode->GetNodeState() == ImageKnifeNodeInternal::NodeState::CLEARED ||
        imageNode->GetNodeVersion() != request->GetVersion()) {
        return true;
    }
    return false;
}

void ImageKnifeDispatcher::CompleteExecutingList(const std::list<IJobQueue::Job> &executingList, const bool &canceled,
                                                 std::shared_ptr<ImageKnifeTaskInternal> task)
{
    for (DefaultJobQueue::Job job : executingList) {
        if (job.request == nullptr) {
            continue;
        }
        std::string info = ImageKnifeTaskInternal::GetTaskInfo(job.type, job.request);
        if (job.request->IsDestroy()) {
            // 合并的请求被取消
            ProcessCanceledRequest(job.request, job.type, "Request Abort. " + task->cancelInfo);
        } else if (IsRequestOverdue(job.request)) {
            // 合并的请求过期
            ProcessCanceledRequest(job.request, job.type, "Request Overdue");
        } else if (canceled) {
            // 如果加载的请求被取消，被合并的请求需要重新排队进行加载
            jobQueuePtr_->Add(job);
            IMAGE_KNIFE_LOG(LOG_DEBUG, "%{public}s Merged Request Enqueue Due To Task Canceled", info.c_str());
        } else if (task->IsSuccess()) {
            // 加载成功
            ProcessSucceedRequest(job.request, job.type, task);
            IMAGE_KNIFE_LOG(LOG_INFO, "%{public}s Loading Success", info.c_str());
        } else {
            IMAGE_KNIFE_LOG(LOG_ERROR, "%{public}s Loading Failed", info.c_str());
            // 加载失败且请求类型为主图
            if (job.type == ImageRequestType::MAIN_SRC) {
                ProcessMainSrcFailedRequest(job.request, task);
            }
        }
    }
}

void ResolvePreloadCacheRequests(const std::list<std::shared_ptr<ImageKnifeRequestInternal>> &preloadCacheRequests,
                                 const std::string &filePath, const bool &result)
{
    for (auto request : preloadCacheRequests) {
        if (result) {
            request->ResolvePromiseFilePath(filePath);
        } else {
            request->ResolvePromiseFilePath(std::string());
        }
    }
}

void ResolveRequestPromise(const std::list<IJobQueue::Job> &executingList,
                           std::shared_ptr<ImageKnifeTaskInternal> task)
{
    IMAGE_KNIFE_CHECK(task == nullptr);
    std::list<std::shared_ptr<ImageKnifeRequestInternal>> preloadCacheRequests;
    for (DefaultJobQueue::Job job : executingList) {
        if (job.request == nullptr) {
            continue;
        }
        if (job.request->IsPreloadCache()) {
            preloadCacheRequests.push_back(job.request);
        }
        if (task->IsSuccess()) {
            job.request->ResolvePromiseImageData(task->product.imageData);
        }
    }

    // 没有preloadCache请求
    if (preloadCacheRequests.empty()) {
        task->promisePreloadCache.set_value(nullptr);
        return;
    }

    std::string filePath = FileCache::GetInstance()->filePath + "/" + task->fileKey;
    if (task->foundFileCache) {
        ResolvePreloadCacheRequests(preloadCacheRequests, filePath, true);
    } else if (task->IsSuccess()) {
        auto func = [preloadCacheRequests, filePath](bool res) {
            ResolvePreloadCacheRequests(preloadCacheRequests, filePath, true);
        };
        // 交由写缓存结束后进行Resolve
        task->promisePreloadCache.set_value(func);
        return;
    }

    task->promisePreloadCache.set_value(nullptr);
}

void ImageKnifeDispatcher::OnComplete(std::shared_ptr<ImageKnifeTaskInternal> task)
{
    IMAGE_KNIFE_CHECK(task == nullptr);
    auto request = task->GetImageKnifeRequestInternal();
    IMAGE_KNIFE_CHECK(request == nullptr);

    try {
        std::list<IJobQueue::Job> executingList;
        auto it = executingJobMap_.find(task->memoryKey);
        if (it == executingJobMap_.end()) {
            // 同步请求，只从缓存加载的请求没有进行合并，无法在执行列表中找到，需要手动处理
            executingList.push_back({.request = request, .type = ImageRequestType::MAIN_SRC});
        } else {
            // 清空旧的列表，避免reload的请求与旧请求合并造成死循环
            executingList = std::move(it->second);
            executingJobMap_.erase(it);
        }

        ResolveRequestPromise(executingList, task);
        CompleteExecutingList(executingList, request->IsDestroy(), task);
    } catch (std::exception err) {
        task->FatalError("Dispatcher::OnComplete " + std::string(err.what()));
    }

    DispatchNextJob();
    // 移除task记录
    request->RemoveTask(task->GetImageRequestType());
}

bool ImageKnifeDispatcher::DisplayImage(std::shared_ptr<ImageKnifeRequestInternal> request,
                                        ImageRequestType type,
                                        std::shared_ptr<ImageDataCache> imageData)
{
    IMAGE_KNIFE_CHECK_RETURN(request == nullptr, false);
    IMAGE_KNIFE_CHECK_RETURN(imageData == nullptr, false);
    if (type == ImageRequestType::PLACE_SRC && request->IsMainSrcComplete()) {
        // 主图已显示的情况下,不显示占位图
        return false;
    }

    auto imageNode = ImageKnifeInternal::GetInstance().GetImageNode(request->GetNodeId());
    if (imageNode != nullptr) {
        // 应用最新图片的属性
        imageNode->ApplyAttribute(type);

        // 显示图片
        auto dataCache = std::dynamic_pointer_cast<ImageDataCacheInternal>(imageData);
        if ((dataCache != nullptr) && imageNode->Display(dataCache, type == ImageRequestType::PLACE_SRC)) {
            return true;
        } else {
            ProcessFailedRequest(request, type, "ImageDataCache Unavailable (Display Image)");
        }
    }

    return false;
}

bool ImageKnifeDispatcher::LoadFromPixelmap(std::shared_ptr<ImageKnifeTaskInternal> task)
{
    IMAGE_KNIFE_CHECK_RETURN(task == nullptr, false);
    auto request = task->GetImageKnifeRequestInternal();
    IMAGE_KNIFE_CHECK_RETURN(request == nullptr, false);
    auto imageKnifeOption = request->GetImageKnifeOption();
    IMAGE_KNIFE_CHECK_RETURN(imageKnifeOption == nullptr, false);

    if (imageKnifeOption->loadSrc.GetType() != DataType::PIXELMAP) {
        return false;
    }

    OH_PixelmapNative *pixelmap = nullptr;
    if (imageKnifeOption->loadSrc.MovePixelMap(pixelmap)) {
        task->product.imageDataCache = std::make_shared<ImageDataCacheInternal>(pixelmap);
        // 获取pixelmap的宽高信息
        OH_Pixelmap_ImageInfo* imageInfo = nullptr;
        if (OH_PixelmapImageInfo_Create(&imageInfo)) {
            if (OH_PixelmapNative_GetImageInfo(pixelmap, imageInfo)) {
                OH_PixelmapImageInfo_GetWidth(imageInfo, &request->GetImageInfo().imageWidth);
                OH_PixelmapImageInfo_GetHeight(imageInfo, &request->GetImageInfo().imageHeight);
            }
            OH_PixelmapImageInfo_Release(imageInfo);
        }
    } else {
        // 如果获取失败，最终会导致显示失败
        task->EchoError("Get Local Pixelmap Failed，Can't Create ImageDataCache");
    }

    // 返回true表示图片资源为本地pixelmap
    return true;
}

bool ImageKnifeDispatcher::LoadSrcFromMemory(IJobQueue::Job job)
{
    try {
        auto request = job.request;
        uint64_t loadMemoryStartTime = ImageKnifeDataNapi::GetTimestamp();
        if (job.imageSrc == nullptr || request == nullptr) {
            return false;
        }

        auto option = request->GetImageKnifeOption();
        IMAGE_KNIFE_CHECK_RETURN(option == nullptr, false);

        auto imageLoader = std::dynamic_pointer_cast<ImageKnifeLoaderInternal>(option->imageLoader);
        IMAGE_KNIFE_CHECK_RETURN(imageLoader == nullptr, false);
        auto task = std::make_shared<ImageKnifeTaskInternal>(job.type, request, job.imageSrc);
        task->memoryKey = job.memoryKey;

        bool display = false;
        // 只有主图并且设置了跳过内存缓存，才不执行
        if (!(request->IsMemoryCacheSkiped() && job.type == ImageRequestType::MAIN_SRC)) {
            display = imageLoader->LoadFromMemory(task);
        }

        if (!display) {
            display = LoadFromPixelmap(task);
        }

        if (!display) {
            // 非pixelMap且无缓存则去排队加载，onStart回调和数据采集在任务从队列中执行时进行
            return false;
        }

        // 图片数据采集
        if (job.type == ImageRequestType::MAIN_SRC) {
            request->GetImageInfo().timeInfo.requestStartTime = loadMemoryStartTime;
            request->GetImageInfo().timeInfo.memoryCheckEndTime = ImageKnifeDataNapi::GetTimestamp();
            request->GetImageInfo().imageHeight = task->product.imageDataCache->GetImageHeight();
            request->GetImageInfo().imageWidth = task->product.imageDataCache->GetImageWidth();
            request->GetImageInfo().type = task->product.imageDataCache->GetImageFormat();
            // onLoadStart回调
            if (option->onLoadListener != nullptr && option->onLoadListener->onLoadStart != nullptr) {
                request->GetImageKnifeOption()->onLoadListener->onLoadStart(request->GetImageInfo());
            }
        }

        if (IsRequestOverdue(request)) {
            // 过期request 不显示
            ProcessCanceledRequest(request, job.type, "Request Overdue");
        } else {
            request->ResolvePromiseImageData(task->product.imageDataCache);
            ProcessSucceedRequest(request, job.type, task);
        }

        return true;
    } catch (std::exception err) {
        std::string info = ImageKnifeTaskInternal::GetTaskInfo(job.type, job.request);
        IMAGE_KNIFE_LOG(LOG_ERROR, "%{public}s [Fatal Error] %{public}s (LoadSrcFromMemory)", info.c_str(), err.what());
    }

    return false;
}

ImageSource *ImageKnifeDispatcher::GetImageSrc(std::shared_ptr<ImageKnifeOption> option, ImageRequestType type)
{
    IMAGE_KNIFE_CHECK_RETURN(option == nullptr, nullptr, "Null ImageKnifeOption");
    ImageSource *data = nullptr;
    switch (type) {
        case ImageRequestType::MAIN_SRC:
            data = &option->loadSrc;
            break;
        case ImageRequestType::PLACE_SRC:
            data = &option->placeholderSrc;
            break;
        case ImageRequestType::ERROR_SRC:
            data = &option->errorSrc;
            break;
        default:
            break;
    }

    if (data != nullptr && data->GetType() == DataType::UNDEFINED) {
        return nullptr;
    }

    return data;
}

bool ImageKnifeDispatcher::ExecuteJob(IJobQueue::Job job)
{
    auto request = job.request;
    IMAGE_KNIFE_CHECK_RETURN(request == nullptr, false, "Null ImageKnifeRequest");
    auto option = request->GetImageKnifeOption();
    IMAGE_KNIFE_CHECK_RETURN(option == nullptr, false, "Null ImageKnifeOption");

    if (job.type == ImageRequestType::MAIN_SRC) {
        // 请求开始时间
        request->GetImageInfo().timeInfo.requestStartTime = ImageKnifeDataNapi::GetTimestamp();
        // js层start回调
        if (option->onLoadListener != nullptr &&
            option->onLoadListener->onLoadStart != nullptr && !request->IsRequeue()) {
            option->onLoadListener->onLoadStart(request->GetImageInfo());
            request->ToggleReQueue();
        }
    }
    IMAGE_KNIFE_CHECK_RETURN(job.imageSrc == nullptr, false);

    auto task = std::make_shared<ImageKnifeTaskInternal>(job.type, request, job.imageSrc);
    task->memoryKey = job.memoryKey;
    task->fileKey = job.fileKey;

    if (job.memoryKey.empty()) {
        task->EchoError("Empty memoryKey (Execute Job)");
        return false;
    }

    // 同步加载不进行合并, 只从缓存中加载不进行合并, 不使用文件缓存的不合并(只有主图可以选择不使用)
    if (job.request->IsSyncLoad() || option->onlyRetrieveFromCache ||
        (job.request->IsFileCacheSkiped() && job.type == ImageRequestType::MAIN_SRC)) {
        return ExecuteTask(task);
    }

    // 合并相同请求
    if (executingJobMap_.find(job.memoryKey) == executingJobMap_.end()) {
        executingJobMap_.emplace(job.memoryKey, std::list<IJobQueue::Job>({job}));
    } else {
        auto &executingList = executingJobMap_[job.memoryKey];
        executingList.emplace_back(job);
        auto &frontJob = executingList.front();
        IMAGE_KNIFE_LOG(LOG_INFO, "%{public}s  Request Merged On %{public}s", task->GetTaskInfo().c_str(),
                        ImageKnifeTaskInternal::GetTaskInfo(frontJob.type, frontJob.request).c_str());
        return false;
    }

    return ExecuteTask(task);
}

bool ImageKnifeDispatcher::ExecuteTask(std::shared_ptr<ImageKnifeTaskInternal> task)
{
    IMAGE_KNIFE_CHECK_RETURN(task == nullptr, false);
    auto request = task->GetImageKnifeRequestInternal();
    IMAGE_KNIFE_CHECK_RETURN(request == nullptr, false);
    auto option = request->GetImageKnifeOption();
    IMAGE_KNIFE_CHECK_RETURN(option == nullptr, false);

    // 设置默认执行：图片url，resource 进行加载解码，图形变换
    AsyncTask func = [this](std::shared_ptr<ImageKnifeTaskInternal> task) {
        this->LoadImageSource(task);
    };

    if (request->IsSyncLoad()) {
        IMAGE_KNIFE_LOG(LOG_INFO, "%{public}s Request SyncLoad", task->GetTaskInfo().c_str());
        func(task);
        OnComplete(task);
    } else {
        AsyncTask completeCallback = [this](std::shared_ptr<ImageKnifeTaskInternal> task) {
            this->OnComplete(task);
        };
        if (!TaskWorker::GetInstance()->PushTask(func, completeCallback, task, ImageKnifeQOS::USER_INITIATED)) {
            if (task->GetImageRequestType() == ImageRequestType::MAIN_SRC) {
                request->GetImageInfo().errorInfo.code = LoadFailedCode::DISPATCH_THREAD;
            }
            if (option->onLoadListener != nullptr &&
                option->onLoadListener->onLoadFailed != nullptr &&
                task->GetImageRequestType() == ImageRequestType::MAIN_SRC) {
                option->onLoadListener->onLoadFailed(task->GetLastError(), request->GetImageInfo());
            }
            request->Destroy();
            return false;
        } else {
            IMAGE_KNIFE_LOG(LOG_INFO, "%{public}s Push Task Success", task->GetTaskInfo().c_str());
        }
    }
    return true;
}

void ImageKnifeDispatcher::TransformImage(std::shared_ptr<ImageKnifeTaskInternal> task)
{
    IMAGE_KNIFE_CHECK(task == nullptr);
    auto request = task->GetImageKnifeRequestInternal();
    IMAGE_KNIFE_CHECK(request == nullptr);
    auto option = request->GetImageKnifeOption();
    IMAGE_KNIFE_CHECK(option == nullptr);

    if (option->multiTransformation != nullptr) {
        option->multiTransformation->Transform(task);
    } else if (option->transformation != nullptr) {
        IMAGE_KNIFE_LOG(LOG_DEBUG, "%{public}s Transform: %{public}s", task->GetTaskInfo().c_str(),
                        option->transformation->GetTransformInfo().c_str());
        // 为当前线程创建EGL上下文
        ImageKnifeEGL egl;
        IMAGE_KNIFE_CHECK(!egl.Init(), "EGL Init Failed");
        option->transformation->Transform(task);
    }
}

// 在主线程中调用
void ImageKnifeDispatcher::CancelRequest(std::shared_ptr<ImageKnifeRequestInternal> request)
{
    IMAGE_KNIFE_CHECK(request == nullptr);
    request->Destroy();

    // 调用对应interceptor的cancel函数
    CancelInterceptor(request, ImageRequestType::MAIN_SRC);
    CancelInterceptor(request, ImageRequestType::PLACE_SRC);
    CancelInterceptor(request, ImageRequestType::ERROR_SRC);
}

void ImageKnifeDispatcher::CancelInterceptor(std::shared_ptr<ImageKnifeRequestInternal> request,
                                             ImageRequestType type)
{
    IMAGE_KNIFE_CHECK(request == nullptr);
    auto task = std::static_pointer_cast<ImageKnifeTaskInternal>(request->GetTask(type));
    if (task != nullptr) {
        auto interceptor = task->GetCurrentInterceptor();
        if (interceptor != nullptr) {
            interceptor->Cancel(task);
        }
    }
}

void ImageKnifeDispatcher::DispatchNextJob()
{
    if (executingJobMap_.size() >= maxRequests) {
        return;
    }

    DefaultJobQueue::Job job = jobQueuePtr_->Pop();
    if (job.request == nullptr) {
        // 当前排队队列为空
        return;
    }

    do {
        if (job.request->GetStatus() == ImageKnifeRequest::Status::PROGRESS ||
                   job.request->GetStatus() == ImageKnifeRequest::Status::ERROR) {
            if (ExecuteJob(job)) { // 任务开启成功
                break;
            }
        } else if (job.request->GetStatus() == ImageKnifeRequest::Status::DESTROY) {
            ProcessCanceledRequest(job.request, job.type, "Request Cancel From Queue", true);
        }

        job = jobQueuePtr_->Pop();
    } while (job.request != nullptr);
}
} //  end of namespace
